﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ImageCompression
{
    public class CompressImage
    {
        #region Fields
        //Thread td;//创建线程
        Image ig = null;

        private List<ImgInfoEntity> _imgList;
        public string _savePath;
        public int _rate;


        //文件后缀
        public string _post = "";

        public System.Windows.Forms.ProgressBar ProgressBar { private get; set; }
        public System.Windows.Forms.Label ProgressText { private get; set; }
        public System.Windows.Forms.DataGridView Dgv { private get; set; }

        int _total, _index;
        #endregion

        #region constructor
        /// <summary>
        /// 图片压缩
        /// </summary>
        /// <param name="imgList">要压缩的图片列表</param>
        /// <param name="rate">缩放比率</param>
        /// <param name="savePath">保存路径</param>
        public CompressImage(List<ImgInfoEntity> imgList, int rate, string savePath, string filePost)
        {
            this._imgList = imgList;
            this._rate = rate;
            this._savePath = savePath;

            this._total = imgList.Count;
            this._index = 0;

            this._post = filePost;
        }

        #endregion

        #region 入口方法
        public void Start()
        {
            string msg = "";
            if (this._imgList == null || this._imgList.Count == 0)
                msg = "请选择要压缩的图片";
            else if (this._rate < 0 || this._rate > 100)
                msg = "压缩比率要介于0~100之间";
            else if (string.IsNullOrEmpty(this._savePath))
                msg = "请选择保存路径";
            if (!string.IsNullOrEmpty(msg))
            {
                System.Windows.Forms.MessageBox.Show(msg, "错误", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                return;
            }

            //td = new Thread(new ThreadStart(this.Compression));//创建线程
            //td.Start();//开始线程

            this.ProgressBar.Minimum = 0;
            this.ProgressBar.Maximum = this._total;
            this.ProgressBar.Value = 0;

            Compression();
        }

        #region 压缩
        private async void Compression()
        {
            foreach (ImgInfoEntity img in _imgList)
            {
                CompressImage2(img.FullPath, this._savePath+"/"+ this._rate.ToString()+"/"+img.FileName , this._rate);
            }
        }
        #endregion

        #endregion

        /// <summary>
        /// 无损压缩图片,在一定文件直接大小(长宽尺寸不压缩)的要求下保证质量最优
        /// </summary>
        /// <param name="sFile">原图片地址</param>
        /// <param name="dFile">压缩后保存图片地址</param>
        /// <param name="flag">压缩质量（数字越小压缩率越高）1-100</param>
        /// <param name="filesize">压缩后图片的最大大小,单位kb</param>
        /// <param name="sfsc">是否是第一次调用</param>
        /// <returns></returns>
        public static bool CompressImage1(string sFile, string dFile, int flag = 90, int filesize = 300, bool sfsc = true)
        {
            //如果是第一次调用，原始图像的大小小于要压缩的大小，则直接复制文件，并且返回true
            FileInfo firstFileInfo = new FileInfo(sFile);
            if (sfsc == true && firstFileInfo.Length < filesize * 1024)
            {
                firstFileInfo.CopyTo(dFile);
                return true;
            }

            Image iSource = Image.FromFile(sFile);
            ImageFormat tFormat = iSource.RawFormat;
            int dHeight = iSource.Height/2;
            int dWidth = iSource.Width/2;
            int sW = 0, sH = 0;

            //按比例缩放
            Size tem_size = new Size(iSource.Width, iSource.Height);
            if (tem_size.Width > dHeight || tem_size.Width > dWidth)
            {
                if ((tem_size.Width * dHeight) > (tem_size.Width * dWidth))
                {
                    sW = dWidth;
                    sH = (dWidth * tem_size.Height) / tem_size.Width;
                }
                else
                {
                    sH = dHeight;
                    sW = (tem_size.Width * dHeight) / tem_size.Height;
                }
            }
            else
            {
                sW = tem_size.Width;
                sH = tem_size.Height;
            }

            Bitmap ob = new Bitmap(dWidth, dHeight);
            Graphics g = Graphics.FromImage(ob);

            g.Clear(Color.WhiteSmoke);
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);

            g.Dispose();

            //以下代码为保存图片时，设置压缩质量
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;

            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }

                if (jpegICIinfo != null)
                {
                    ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径
                    FileInfo fi = new FileInfo(dFile);
                    if (fi.Length > 1024 * filesize)
                    {
                        flag = flag - 10;
                        CompressImage1(sFile, dFile, flag, filesize, false);
                    }
                }
                else
                {
                    ob.Save(dFile, tFormat);
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                iSource.Dispose();
                ob.Dispose();
            }
        }

        /// <summary>
        /// 无损压缩图片,在一定文件直接大小(长宽尺寸不压缩)的要求下保证质量最优
        /// </summary>
        /// <param name="sFile">原图片地址</param>
        /// <param name="dFile">压缩后保存图片地址</param>
        /// <param name="flag">压缩质量（数字越小压缩率越高）1-100</param>
        /// <returns></returns>
        public static bool CompressImage2(string sFile, string dFile, int flag = 90)
        {
            Image iSource = Image.FromFile(sFile);
            ImageFormat tFormat = iSource.RawFormat;
            int dHeight = iSource.Height / 2;
            int dWidth = iSource.Width / 2;
            int sW = 0, sH = 0;
            
            Bitmap ob = new Bitmap(dWidth, dHeight);
            Graphics g = Graphics.FromImage(ob);

            g.Clear(Color.WhiteSmoke);
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);

            g.Dispose();

            //以下代码为保存图片时，设置压缩质量
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;

            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }

                if (jpegICIinfo != null)
                {
                    ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径
                }
                else
                {
                    ob.Save(dFile, tFormat);
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                iSource.Dispose();
                ob.Dispose();
            }
        }

    }
}